在這環節中,我會以前兩天實做的 HTML 架構進行 CSS 的樣式表實做,進行美化排版。之前修過 UI / UX 的課程,發現這些視覺內容的呈現真的是很高深的學問,可能會讓人卻步,但實際上在實做中,我們只需要思考「如何呈現能讓重點更加突出?」或許這問題就會解決一半了,這一期內容就會來聊聊這部份。
這也是我在初學時,很好奇的一個問題。我們知道在前端開發中,有一個最重要的原則就是「關注點分離」。我們知道 HTML 是處理結構、CSS 是處理樣式、JavaScript 是處理行為。而實務上,樣式的呈現通常會比行為還更容易確定,因為 CSS 主要就是單純處理外觀問題,而在 JavaScript 實作互動設計時,經常就會涉及到較複雜的功能實做、以及前後端資料傳輸與邏輯處理等等的複雜情況。因此,如果我們先把基礎的 CSS 元素與外觀架構先實做出來,那後面就可以看著你要執行的**「實體」(物件)**進行 JavaScript 互動設計,這樣我們大腦就可以空出更多時間來思考互動實做,而不用一直花心思記得這個物件到底要做什麼了。
早期的 HTML 主要是為了在網頁中架設文件的結構,當時的語法對於外觀和樣式的控制其實相當有限。當時,網頁的樣式主要是透過 inline styles,也就是直接把樣式設定「嵌入」(Embed)到 HTML 標記中。可想而知,當我們要針對一個樣式做比較多控制的時候,就會發現該標記過於龐大且複雜,網頁工程師進行在座例行網頁維護工作時就會出現大麻煩了。
在 CSS 出現以前,當時為了控制網頁的外觀,網頁工程師只能夠過當時 HTML 1.0 中的樣式語法進行設定,例如 <font>
用來控制文字的字體大小和顏色、<center>
用來將內容置中、而 <b>
和 <i>
用來顯示粗體或斜體文字。如果我們用當年 HTML 1.0 的語法,大概會像這樣:
<body>
<center>
<font face="Arial" size="5" color="red">
<b><i>This is the Title</i></b>
</font>
</center>
<p>
<font face="Times New Roman" size="3" color="blue">
<i>This is the blue text with Times New Roman font.</i>
</font>
</p>
</body>
畢竟每一個標記都是「逐項」設定的,就想像你要一次修改 200 個標記設定,那會有多刺激~
也正式因為如此,網頁的設計越來越複雜的時候,我們就會希望可以從一個固定的地方來控制網頁的樣式,讓呈現的網頁內文可以跟樣式分離。在當年的確有幾的除了 CSS 之外的解決方案,就是 DSSSL,但這語法複雜到不適合做簡單的網頁樣式設計。於是到 1994 年,當時一樣在 CERN 工作的 Håkon Wium Lie 就提出了 Cascading Style Sheets(CSS) 的構想,包含:
這想法一提出就得到 W3C 鼎力支持。但瀏覽器開發廠商似乎就不是這樣想了~我們待會再說。
Source: https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/CSS_basics
當時的 CSS 在語法撰寫上有這些名詞:
Selector:選擇器
這是在 Ruleset 最前面的 HTML 標記名稱,用來定義我們要套用樣式的元素(在這個範例中,是 <p>
元素)。若你要控制其他標記的樣式,只需更改 Selector 即可。
Property:屬性
這是你要定義 HTML 標記樣式的方式,在這個例子中,color
是 <p>
標記的一個屬性。
Property Value:屬性值
在冒號(:)的後面是 Property Value,決定某個屬性要被改成什麼樣式,而要被修改的標記屬性就是變成紅色。
Declaration:宣告
這是一個「單一的」規則,就像上面的 color: red;
,這樣 <p>
標記的內容是文字,也就是文字變成紅色了。單一宣告之間要用分號(;)隔開。
Ruleset:規則集
所有該標記中的每個樣式 Declaration 的集合就是 Ruleset,必須用大括號 {}
包起來。
當時有定義以下屬性:
font-family
、font-size
)。line-height
)、對齊(text-align
)。margin
)、內距(padding
)和邊框(border
)float
和 clear
實現簡單的佈局控制。<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example of CSS Selector</title>
<style>
... [CSS Syntaxes Go Here]
</style>
</head>
<body>
<h1>This is Heading 1</h1>
<h2>This is Heading 2</h2>
<h3>This is Heading 3</h3>
<div **id="header"**>
<p>This paragraph is controlled by **ID Selector.**</p>
</div>
**<p>**This paragraph is controlled by **Element Selector.**</p>
<p **class="example"**>This paragraph is controlled by **Class Selector.**</p>
</body>
</html>
當年的 CSS 1.0 只有最基礎的 Selector,我們用以上的 HTML 文件來看,看看下面的 CSS 對應到哪些標記:
Element(元素) Selector:對指定 HTML 元素應用樣式,如 p
或 h1
。
p {
color: blue;
}
Class Selector(類別):用 .
來選擇帶有特定 class 屬性的元素。
.example {
color: green;
}
ID Selector:用 #
來選擇具有唯一 ID 的元素。
#header {
background-color: yellow;
}
Group(群組)Selector:可以一次為多個元素應用相同的樣式,使用逗號分隔。
h1, h2, h3 {
color: red;
}
CSS 1.0 提供了多種與文字樣式相關的屬性:
字體樣式:
font-family
:定義字體系列,我們可以設定很多字體做為備用。
p {
font-family: Arial, sans-serif;
}
font-size
:設定字體大小,方式有分為
px
(像素)、pt
(點)。em
或是 %
,也就是相對於父元素(追溯到上一層級)的字體大小。#header p {
font-size: 16px;
}
font-style
:設定字體樣式,如斜體(italic
)。
h1, h2, h3 {
font-style: italic;
}
font-weight
:設定字體粗細,如加粗(bold
)。
p {
font-weight: bold;
}
文字顏色 color
:
h1 {
color: blue;
}
文字對齊 text-align
:如置中對齊(center
)、靠左對齊(left
)、靠右對齊(right
)。
#header {
text-align: center;
}
文字裝飾 text-decoration
:如底線(underline
)。
h2 {
text-decoration: underline;
}
行高(間距)line-height
:
p.example {
line-height: 1.5;
}
背景顏色 background-color
:你也可以在選擇器中寫 body
來控制整個頁面的顏色。
p {
background-color: lightgrey;
}
設定背景圖片 background-image
:
body {
background-image: url('background.jpg');
}
設定背景重複 background-repeat
:選項有 repeat
(重複)、no-repeat
(不重複)、repeat-x
(僅水平重複)和 repeat-y
(僅垂直重複)。
body {
background-repeat: no-repeat;
}
設定背景位置 background-position
:選項有 top
、center
、bottom
等。
body {
background-position: center;
}
CSS 1.0 引入了盒模型的概念,這是一個用來控制元素空間和邊距的核心機制,包括 margin
、padding
、border
這些屬性:
Border(邊框):選項有 border-width
(設定邊框寬度);border-style
:(設定邊框樣式,如實線 solid
、虛線 dashed
);border-color
:設定邊框顏色。
p {
border-width: 1px;
border-style: solid;
border-color: black;
}
內框距 padding
:設定元素內部內容與內框之間的距離。
p {
padding: 10px;
}
外框距 margin
:設定元素外部與其他元素(或外框)之間的距離。
p {
margin: 20px;
}
CSS 1.0 提供了簡單的佈局控制功能,主要通過 float
和 clear
來控制元素的排列:
浮動 float
:允許元素可以向左或向右移動,其他元素會圍繞 float
屬性的物件排列。
img {
float: left;
}
清除浮動 clear
:用來控制元素如何清除浮動,選項包括 left
、right
和 both
。
p {
clear: both;
}
這裡包含設定無序列表(<ul>
)和有序列表(<ol>
)的樣式
列表樣式類型 list-style-type
:設定列表項目的符號樣式,如 disc
(空心圓)、circle
(實心圓)、square
(方形)、或 decimal
(數字)。
ul {
list-style-type: square;
}
列表樣式圖片 list-style-image
:使用圖片作為列表符號。
ul {
list-style-image: url('bullet.png');
}
在 1990 年代初期,Netscape Navigator 瀏覽器的市占率達到八成的壟斷程度,然而微軟在 1995 年推出 **Internet Explorer(IE)**開始攻佔市場。這兩間公司就開始進入「瀏覽器戰爭」。雖然在 CSS 推出後,Internet Explorer 3 和 Netscape Navigator 4 都有支援一些 CSS 語法,但是當時他們各自希望建立的網頁生態圈 Netscape Layer 與 MS 的 VBScript 和 ActiveX,因此光是用開發的新技術來打架都來不及了,根本就不太花心思去開發 W3C 標準的 CSS。也正因如此,網頁工程師就必須要寫兩套 Code 來分別符合這兩家公司自己開發的標準,畢竟在他們各自的立場來看,如果規範統一了,那誰還要用我自家的瀏覽器?
這問題一直到 1998 年,當時網路社群的一些大老就開始發起 Web Standards Project(WaSP)的活動,主要在譴責這些瀏覽器廠商忽略這些標準的推動。而在這些使用者的「施壓」之下,才讓 Netscape 跟 Microsoft 開始妥協去接受 W3C 的 CSS 標準。後來我想他們也在統一規範之後,就讓開發環境變得輕鬆許多了吧~
雖然 CSS 推出的時候得到廣泛支持,但畢竟做為第一代這種具有「實驗」性質的突破來說,很快就遇到不足的部份。這樣講太抽象了,舉一些具體案例:
<table>
標記進行實做,也就是表格內還有表格,這對當時的硬體資源相對薄弱而導致算力不足的網頁瀏覽器來說,可能就直接喝西北風了。雖然 CSS 1 的 float
屬性能讓元素自己浮動到旁邊,但在各欄位之間要上下對齊的時候就是一個大問題了,我想解決方式只有「合成圖片」了吧~:hover
這種 Pseudo-class 語法(我們後面 CSS 2 就會提到),所以你也只能用 JavaScript 進行實做,可想而知有多麻煩!padding
和 margin
來調整 Box Model 的間距。但他發現在 IE 和 Netscape 上顯示的效果根本完全不同。Netscape 則根據 W3C 的標準進行渲染,但是當年 IE 的 Box Model 計算方式是錯誤的,因為 padding 跟 margin 竟然同時被拿來算元素的寬度,這就直接導致兩個瀏覽器下的佈局會直接走樣。所以你被主管要求要寫兩份 CSS 來處理相容性問題,你的 CSS 工作量就加倍了。基本上,CSS 1 的出現雖然在網頁設計歷史上算是一個重大突破,但仍無法當時在網頁實作上的需求,包含較為複雜布局、對不同界面要另外設計樣式、瀏覽器呈現的樣式也不一致...等,這些問題都讓 CSS 1 顯得相當不足,而這也讓 W3C 趕緊摧生出 CSS 2 來解決這些問題,基於 CSS 1 之上進行功能強化,對當時來說這樣的突破已經是「里程碑」了。而語法上,你會發現 CSS 的結構真的相當簡單,最困難的應該就是排版了吧~